package com.lwq.im.chartdemo.session;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.lwq.im.chartdemo.constants.Constants;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.stream.Collectors;

/**
 * 在线会话
 */

@Component
public class OnlineSession {


    /**
     * key: userId, value: Channel集合
     */
    private ConcurrentHashMap<String, Collection<Channel>> onlineSession = new ConcurrentHashMap<String, Collection<Channel>>();


    public Integer getOnlineCount(){
        return onlineSession.size();
    }

    public List<String> getOnlineUserId(){
        if (CollectionUtil.isEmpty(onlineSession)){
            return Collections.EMPTY_LIST;
        }
        return onlineSession.keySet().stream().collect(Collectors.toList());
    }


    public Map<String, Collection<Channel>> getOnlineSession(){
        //return (ConcurrentHashMap<String, Collection<Channel>>) Collections.unmodifiableMap(onlineSession);
        return  Collections.unmodifiableMap(onlineSession);
    }

    private final transient ChannelFutureListener removeListener = new ChannelFutureListener() {
        @Override
        public void operationComplete(ChannelFuture future){
            future.removeListener(this);
            remove(future.channel());
        }
    };

    /**
     * 获取用户id
     *
     * @param channel
     * @return
     */
    public String getUserId(Channel channel){
        return channel.attr(Constants.ChannelAttrKye.USER_ID).get();
    }



    public void put(Channel channel){
        String userId = getUserId(channel);
        if (StrUtil.isBlank(userId) || !channel.isActive()){
            return;
        }
        channel.closeFuture().addListener(removeListener);


        Collection<Channel> channels = onlineSession.putIfAbsent(userId, new ConcurrentLinkedQueue<>(Collections.singletonList(channel)));
        if (CollectionUtil.isNotEmpty(channels)){
            channels.add(channel);
        }
        if (!channel.isActive()){

            remove(channel);
        }

    }

    public void remove(Channel channel){

        String userId = getUserId(channel);
        if (StrUtil.isBlank(userId)){
            return;
        }

        Collection<Channel> channels = onlineSession.get(userId);
        if (CollectionUtil.isNotEmpty(channels)){
            channels.remove(channel);
        }
        if (CollectionUtil.isEmpty(channels)){
            onlineSession.remove(userId);
        }


    }



}
